package com.bc.bcapi.utils.web3j;

import com.bc.bccore.web3j.WalletService;
import com.bc.bcmodel.domain.T_Erc_contractModel;
import org.web3j.utils.Convert;

import java.io.IOException;
import java.math.BigDecimal;

public class GasService {

    private static GasService gasService = new GasService();

    private static final int ETHGASLIMIT = 21000;
    private static final int CONTRACTGASLIMIT = 210000;
    private static final BigDecimal COMMISSIONRATE = new BigDecimal(0.003);
    private static final BigDecimal GASPRICEINCERATE = new BigDecimal(1.05);
    private static final int DEFAULTSCALE = 8;

    private T_Erc_contractModel contractModel;

    public static GasService getInstance() {
        return gasService;
    }

    public GasService setContractModel(T_Erc_contractModel contractModel) {
        this.contractModel = contractModel;
        return this;
    }

    private BigDecimal withdrawValue;

    public GasService withdraw(BigDecimal value) throws Exception {
        if (contractModel == null) {
            throw new Exception("not set contract yet");
        }
        this.withdrawValue = value;
        return this;
    }

    BigDecimal gas;
    BigDecimal commission;

    public Decomposition decomposit() throws Exception {
        if (contractModel == null) {
            throw new Exception("not set contract yet");
        }
        if (withdrawValue == null) {
            throw new Exception("not set value yet");
        }

        commission = getCommission();

        Decomposition decomposition = new Decomposition();
        //commission
        decomposition.setCommission_contract(contractModel);
        decomposition.setCommission_value(commission);

        //gas price
        BigDecimal gasPrice = getGasPrice();
        //gas limit
        int gasLimit = getGasLimit();
        //gas
        gas = gasPrice.multiply(new BigDecimal(gasLimit));
        //actualwithdraw
        BigDecimal actualWithdrawValue = getActualWithdrawValue();

        decomposition.setActual_receipt_contract(contractModel);
        decomposition.setActual_receipt_value(actualWithdrawValue);
        decomposition.setGas(gas);
        decomposition.setGasPrice(gasPrice);
        decomposition.setGasLimit(gasLimit);

        return decomposition;
    }

    private int getGasLimit() {

        int contract_gas_limit = contractModel.getGaslimit();

        if (contractModel.getContract_id().equals(Util.getETHID())) {
            return contract_gas_limit == 0 ? ETHGASLIMIT : contract_gas_limit;
        }

        return contract_gas_limit == 0 ? CONTRACTGASLIMIT : contract_gas_limit;

    }

    private BigDecimal getGasPrice() throws IOException {
        return Convert.fromWei(WalletService.getInstance().gasPrice().toString(), Convert.Unit.ETHER).multiply(GASPRICEINCERATE).setScale(DEFAULTSCALE, BigDecimal.ROUND_UP);
    }

    private BigDecimal getActualWithdrawValue() {
        return contractModel.getContract_id().equals(Util.getETHID()) ? withdrawValue.subtract(commission).subtract(gas) : withdrawValue.subtract(commission);
    }

    private BigDecimal getCommission() {
        int decimal = 0;
        int indexof = withdrawValue.toString().indexOf(".");
        if (indexof > 0) {
            decimal = withdrawValue.toString().length() - 1 - indexof;
        }

        int scale = decimal < contractModel.getDigit() ? decimal : contractModel.getDigit();

        return withdrawValue.multiply(COMMISSIONRATE).setScale(scale, BigDecimal.ROUND_UP);
    }


}
